#include "uart_utils.h"
#include "mem_utils.h"

/**
 * init uart
 * 
 * @param pDev the uart device
 * @param baud the baud rate
 * @param data_bits the data bits
 * @param stop_bits the stop bits
 * @param parity the parity
 * 
 * @return void
 */
static void stm32f407_uart_init(struct uart_device *pDev, int baud, int data_bits, int stop_bits, int parity)
{
	
}

/**
 * send data to uart
 * 
 * @param pDev the uart device
 * @param data the data to be sent
 * @param length the length of the data
 * 
 * @return void
 */
static void stm32f407_uart_send(struct uart_device *pDev, unsigned char *data, int length)
{
    for(int i = 0; i < length; i++)
    {
        
    }
}

/**
 * recv data from uart
 * 
 * @param pDev the uart device
 * @param data the data to be received
 * 
 * @return void
 */
static void stm32f407_uart_recv(struct uart_device *pDev, unsigned char *data)
{
    
}


struct uart_device g_uart_device_1 = {
    .name = "uart1",
    .init = stm32f407_uart_init,
    .send = stm32f407_uart_send,
    .recv = stm32f407_uart_recv,
    .priv_data = USART1,
};


struct uart_device *g_uart_device[] = {
    &g_uart_device_1,
};



/**
 * find uart device
 * 
 * @param name the name of the uart device
 * 
 * @return the uart device
 */

struct uart_device * find_uart_device(char *name)
{
    for(int i = 0; i < sizeof(g_uart_device) / sizeof(g_uart_device[0]); i++)
    {
        if(mymemcmp(g_uart_device[i]->name, name, sizeof(g_uart_device[i]->name)) == 0)
        {
            return g_uart_device[i];
        }
    }
		
		return (struct uart_device *)0xFFFFFFFF;
		
}

/**
 * put char to uart
 * 
 * @param data the char to be put
 * 
 * @return void
 */
void myputchar(char data)
{
    
}

/**
 * get char from uart
 * 
 * @param void
 * 
 * @return the char got
 */
char mygetchar(void)
{
	
	
	
	return 1;
}

/**
 * put string to uart
 * 
 * @param str the string to be put
 * 
 * @return void
 */
void myputstr(const char *str)
{
	while (*str)
	{
		
		str++;
	}
}


void dec2hex(unsigned int dnum)
{

}


/**
 * put hex to uart
 * 
 * @param hex the hex to be put
 * 
 * @return void
 */
void myputhex8(unsigned char val)
{
    unsigned char temp_val;

    // the high 4 bits
    temp_val = (val >> 4) & 0x0F;
    if(temp_val > 9)
        myputchar(temp_val + 'A' - 10);
    else
        myputchar(temp_val + '0');

    // the low 4 bits
    temp_val = val & 0x0F;
    if(temp_val > 9)
        myputchar(temp_val + 'A' - 10);
    else
        myputchar(temp_val + '0');

}

/**
 * put 16-bit hex value to uart
 * 
 * @param val the 16-bit value to be converted and output as hex
 * 
 * @return void
 * 
 */
void myputhex16(unsigned short val)
{
    unsigned short temp_val = val;

    myputhex8(temp_val & 0xff00);
    myputhex8(temp_val & 0x00ff);
}


/**
 * put 32-bit hex value to uart
 * 
 * @param val the 32-bit value to be converted and output as hex
 * 
 * @return void
 */
void myputhex32(unsigned int val)
{
    unsigned int temp_val = val;

    myputhex8(temp_val & 0xff000000);
    myputhex8(temp_val & 0x00ff0000);
    myputhex8(temp_val & 0x0000ff00);
    myputhex8(temp_val & 0x000000ff);
}

/**
 * put decimal value to uart
 * 
 * @param val the decimal value to be converted and output as decimal
 * 
 * @return void
 */
void myputdec(unsigned int val)
{
	unsigned int temp_val = val;
    unsigned int divisor = 1;
    unsigned int digit;

    // Handle special case: if val is 0, output '0'
    if (val == 0)
    {
        myputchar('0');
        return;
    }

    // Find the appropriate divisor (10^n where n is the number of digits - 1)
    while (temp_val >= 10)
    {
        divisor *= 10;
        temp_val /= 10;
    }
    
    // Reset temp_val to original value
    temp_val = val;
    
    // Extract and output each digit from left to right
    while (divisor > 0)
    {
        digit = temp_val / divisor;
        myputchar(digit + '0');
        temp_val %= divisor;
        divisor /= 10;
    }
}

/**
 * put float value to uart
 * 
 * @param val the float value to be converted and output as decimal
 * 
 * @return void
 */
void myputfloat(float val)
{
    unsigned int int_part = (unsigned int)val;
    unsigned int frac_part = (unsigned int)((val - int_part) * 10000);

    // Handle negative numbers
    if (val < 0)
    {
        myputchar('-');
        int_part = (unsigned int)(-val);
        frac_part = (unsigned int)((-val - int_part) * 10000);
    }

    myputdec(int_part);
    myputchar('.');
    myputdec(frac_part);
}

/**
 * put binary value to uart
 * 
 * @param val the binary value to be converted and output as binary
 * @param fill_mode if 1, pad with leading zeros to 8 bits; if 0, output without padding
 * 
 * @return void
 */
void myputbin(unsigned int val, unsigned char fill_mode)
{
	unsigned int temp_val = val;
    unsigned int divisor = 1;
    unsigned int digit;
    unsigned char bit_count = 0;

    // Handle special case: if val is 0
    if (val == 0)
    {
        if (fill_mode)
        {
            // Output 8 zeros when fill_mode is enabled
            for (int i = 0; i < 8; i++)
            {
                myputchar('0');
            }
        }
        else
        {
            myputchar('0');
        }
        return;
    }

    // Find the appropriate divisor (2^n where n is the number of bits - 1)
    while (temp_val >= 2)
    {
        divisor *= 2;
        temp_val /= 2;
        bit_count++;
    }
    bit_count++; // Add 1 for the last bit
    
    // Reset temp_val to original value
    temp_val = val;
    
    // If fill_mode is enabled and we have less than 8 bits, pad with leading zeros
    if (fill_mode && bit_count < 8)
    {
        for (int i = 0; i < (8 - bit_count); i++)
        {
            myputchar('0');
        }
    }
    
    // Extract and output each bit from left to right
    while (divisor > 0)
    {
        digit = temp_val / divisor;
        myputchar(digit + '0');
        temp_val %= divisor;
        divisor /= 2;
    }   
}








